﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections;

namespace Common
{
	/// <summary>
	/// Helper class to simplify work with XmlDocument
	/// </summary>
	public static class XmlExtension
	{
		public static XmlNodeList SelectTypedNodes(this XmlNode node, string xpath, XmlNamespaceManager xnmgr)
		{
			if (node == null || string.IsNullOrEmpty(xpath))
				return null;

			if (xnmgr != null)
				return node.SelectNodes(xpath, xnmgr);
			else
				return node.SelectNodes(xpath);
		}

		public static bool ContainsSubNode(this XmlNode node, string subName)
		{
			if (node == null || string.IsNullOrEmpty(subName) || !node.HasChildNodes)
				return false;

			bool result = false;
			foreach (XmlNode n in node.ChildNodes)
			{
				if (n.Name.ToLower() == subName.ToLower())
				{
					result = true;
					break;
				}
			}
			return result;
		}

		public static bool ContainsAttribute(this XmlNode node, string attName, XmlNamespaceManager xnmgr)
		{
			if (xnmgr != null)
			{
				if (node == null || string.IsNullOrEmpty(attName) || node.Attributes[attName, xnmgr.LookupNamespace("xmlns")] == null)
					return false;

				return true;
			}
			else
			{
				if (node == null || string.IsNullOrEmpty(attName) || node.Attributes[attName] == null)
					return false;

				return true;
			}
		}

		public static XmlElement FindCreateElement(XmlElement parent, string tagName, string name)
		{
			XmlElement elem = null;
			if (name != "")
			{
				System.Collections.IEnumerator enumerator = parent.ChildNodes.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						XmlNode node = (XmlNode)enumerator.Current;
						if ((int)node.NodeType == 1)
						{
							XmlElement temp = (XmlElement)node;
							if (temp.Name == tagName && temp.GetAttribute("Name") == name)
							{
								elem = temp;
								break;
							}
						}
					}
				}
				finally
				{
					IDisposable disposable = enumerator as IDisposable;
					if (disposable != null)
					{
						disposable.Dispose();
					}
				}
			}
			if (elem == null)
			{
				elem = parent.OwnerDocument.CreateElement(tagName);
				parent.AppendChild(elem);
			}
			return elem;
		}

		public static void MergeNode(XmlElement target, XmlElement source)
		{
			IEnumerator enumerator = source.Attributes.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					XmlAttribute attr = (XmlAttribute)enumerator.Current;
					string attrName = attr.Name;
					if (!target.HasAttribute(attrName))
					{
						target.SetAttribute(attrName, attr.Value);
					}
					else
					{
						string targetAttrValue = target.GetAttribute(attrName);
						if (targetAttrValue.IndexOf("$(NoInherit)") < 0)
						{
							if (targetAttrValue.IndexOf("$(Inherit)") >= 0)
							{
								targetAttrValue.Replace("$(Inherit)", attr.Value);
							}
							else
							{
								if (attrName == "AdditionalIncludeDirectories")
								{
									targetAttrValue = targetAttrValue + ';' + attr.Value;
								}
								else
								{
									if (attrName == "AdditionalOptions" || attrName == "AdditionalDependencies")
									{
										targetAttrValue = targetAttrValue + ' ' + attr.Value;
									}
								}
							}
							target.SetAttribute(attrName, targetAttrValue);
						}
					}
				}
			}
			finally
			{
				IDisposable disposable = enumerator as IDisposable;
				if (disposable != null)
				{
					disposable.Dispose();
				}
			}
			System.Collections.IEnumerator enumerator2 = source.ChildNodes.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					XmlNode node = (XmlNode)enumerator2.Current;
					if ((int)node.NodeType == 1)
					{
						XmlElement temp = (XmlElement)node;
						XmlElement childElement = FindCreateElement(target, temp.Name, temp.GetAttribute("Name"));
						MergeNode(childElement, temp);
					}
				}
			}
			finally
			{
				IDisposable disposable2 = enumerator2 as IDisposable;
				if (disposable2 != null)
				{
					disposable2.Dispose();
				}
			}
		}

		public static void MergePropertySheet(XmlElement configElement, string sheetFileName)
		{
			XmlDocument doc = new XmlDocument();
			doc.Load(sheetFileName);
			doc.DocumentElement.RemoveAttribute("ProjectType");
			doc.DocumentElement.RemoveAttribute("Version");
			doc.DocumentElement.RemoveAttribute("Name");
			MergeNode(configElement, doc.DocumentElement);
		}

		/// <summary>
		/// Check if XmlNode contains subNode that reffered to resource file
		/// </summary>
		/// <param name="node"></param>
		/// <param name="resourceName"></param>
		/// <returns></returns>
		public static bool ContainsResourceFile(this XmlDocument doc, XmlNamespaceManager xnmgr, string resourceName = ".resx")
		{
			if (doc == null || string.IsNullOrEmpty(resourceName))
				return false;

			XmlNodeList nodes = doc.DocumentElement.SelectNodes("prj:ItemGroup/prj:EmbeddedResource", xnmgr);
			if (nodes != null && nodes.Count > 0)
			{
				foreach (XmlNode subNode in nodes)
				{
					if (subNode.Name == "EmbeddedResource" && subNode.Attributes["Include"].Value.Contains(resourceName))
					{
						return true;
					}
				}
			}

			return false;
		}

		public static List<Entities.EmbeddedResources> GetResourceFile(this XmlDocument doc, XmlNamespaceManager xnmgr)
		{
			if (doc == null || xnmgr == null)
				return new List<Entities.EmbeddedResources>();

			XmlNodeList nodes = doc.DocumentElement.SelectNodes("prj:ItemGroup/prj:EmbeddedResource", xnmgr);
			if (nodes != null && nodes.Count > 0)
			{
				var list = new List<Entities.EmbeddedResources>();
				foreach (XmlNode subNode in nodes)
				{
					if (subNode.Name == "EmbeddedResource" && subNode.SelectSingleNode("prj:Generator", xnmgr) != null
						&& subNode.SelectSingleNode("prj:Generator", xnmgr).InnerText == "ResXFileCodeGenerator")
					{
						Common.Entities.EmbeddedResources embResource = new Common.Entities.EmbeddedResources();
						embResource.Name = subNode.Attributes["Include"].Value;
						foreach (XmlNode nodePar in subNode.ChildNodes)
						{
							switch (nodePar.Name)
							{
								case "LastGenOutput":
									embResource.LastGenOutput = nodePar.InnerText;
									break;

								case "Generator":
									embResource.Generator = nodePar.InnerText;
									break;

								default: break;
							}
						}

						list.Add(embResource);
					}
				}
				return list;
			}

			return new List<Entities.EmbeddedResources>();
		}

		public static int GetIndexOfItemGroupForProperties(this XmlDocument doc, XmlNamespaceManager xnmgr)
		{
			if (doc == null || xnmgr == null)
				return -1;

			var nodeList = doc.SelectNodes("/prj:Project/prj:ItemGroup", xnmgr);

			if (nodeList == null || nodeList.Count == 0)
				return -1;
			bool found = false;
			int indx = 0;
			foreach (XmlNode node in nodeList)
			{
				foreach (XmlNode subNode in node)
				{
					if (subNode.Name == "Compile" && subNode.Attributes["Include"] != null && subNode.Attributes["Include"].Value == @"Properties\AssemblyInfo.cs")
					{
						found = true;
						break;
					}
				}
				if (found)
					break;
				indx++;
			}

			return indx;
		}

	}
}
